package org.ala.tiktools.rocketmq;

import org.springframework.util.ClassUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ala
 * @date 2024-12-03 13:10
 */
public class MethodUtils {


    /**
     *  找到类中所有指定注解的方法
     */
    public static <T extends Annotation> Map<T, Method> findMethods(Class<?> clazz, Class<T> annoClass) {
        Map<T, Method> map = new HashMap<>();
        //  遍历本类的所有方法
        map.putAll(findMethodsByClass(clazz, annoClass));

        //  遍历直属父类的所有方法
        map.putAll(findMethodsByClass(clazz.getSuperclass(), annoClass));

        //  遍历接口的所有方法
        Class<?>[] itfs = clazz.getInterfaces();
        for (Class<?> itf : itfs) {
            map.putAll(findMethodsByClass(itf, annoClass));
        }

        return map;
    }
    public static <T extends Annotation> Map<T, Method> findMethodsByClass(Class<?> clazz, Class<T> annoClass) {
        Map<T, Method> map = new HashMap<>();
        if (clazz == null) {return map;}
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            T anno = m.getAnnotation(annoClass);
            if (anno != null) {
                map.put(anno, m);
            }
        }
        return map;
    }


    /**
     *  从方法中找指定类型的注解
     */
    public static <T extends Annotation> T getAnnotation(Method method, Class<T> clazz) {
        T anno = method.getAnnotation(clazz);
        //  如果本类能找到直接返回本类的注解
        if (anno != null) { return anno; }

        //  如果本类找不到递归找父类的注解
        Class<?> superClass = method.getClass().getSuperclass();
        Method superMethod = getMethod(superClass, method);
        if (superMethod != null) {
            anno = superMethod.getAnnotation(clazz);
            if (anno != null) {
                return anno;
            }
        }

        //  如果父类找不到从接口中找
        Class<?>[] interfaces = method.getClass().getInterfaces();
        for (Class<?> itf : interfaces) {
            Method itfMethod = getMethod(superClass, method);
            if (itfMethod != null) {
                anno = itfMethod.getAnnotation(clazz);
                if (anno != null) {
                    return anno;
                }
            }
        }

        return null;
    }
    /**
     *  从指定类中找指定方法
     */
    public static Method getMethod(Class<?> clazz, Method method) {
        try {
            return ClassUtils.getMethod(clazz, method.getName(), method.getParameterTypes());
        } catch (Exception e) {
            return null;
        }
    }
}
